package project.one.adk;


import project.one.adk.polygon.Point;
import project.one.adk.polygon.Polygon;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class ControlView extends View {
	private static final int DEFAULT_SIZE = 100;
	private static final int PADDING = 80;
	
	private Paint mPaint;
	private Paint mTouchPaint;
	
	Point touchPoint = new Point();
	boolean drawTouchPoint = false;
	Polygon polygonForwardLeft, polygonForward, polygonForwardRight, polygonBackwardLeft, polygonBackward, polygonBackwardRight, polygonStop;
	DirectionListener directionListener;
	String where = "";
	
	interface DirectionListener {
		void goForwardLeft();
		void goForward();
		void goForwardRight();
		void goBackwardLeft();
		void goBackward();
		void goBackwardRight();
		void goStop();
	}
	
	public ControlView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}
	
	private void init() {
		mPaint = new Paint();
		mPaint.setAntiAlias(true);
		mPaint.setColor(0xFFFFFFFF);
		
		mTouchPaint = new Paint();
		mTouchPaint.setAntiAlias(true);
		mTouchPaint.setColor(0x77FFFF00);
	}
	
	public void setListener(DirectionListener listener) {
		directionListener = listener;
	}
	
	private void initVert() {
		polygonForwardLeft = Polygon.Builder()
				.addVertex(new Point(0, getHeight()/2))
				.addVertex(new Point(getWidth()/2, getHeight()/2))
				.addVertex(new Point(PADDING, 0))
				.addVertex(new Point(0, 0))
				.build();
		polygonForward = Polygon.Builder()
				.addVertex(new Point(getWidth()/2, getHeight()/2))
				.addVertex(new Point(getWidth()-PADDING, 0))
				.addVertex(new Point(PADDING, 0))
				.build();
		polygonForwardRight = Polygon.Builder()
				.addVertex(new Point(getWidth()/2, getHeight()/2))
				.addVertex(new Point(getWidth(), getHeight()/2))
				.addVertex(new Point(getWidth(), 0))
				.addVertex(new Point(getWidth()-PADDING, 0))
				.build();
		polygonBackwardLeft = new Polygon.Builder()
				.addVertex(new Point(0, getHeight()/2))
				.addVertex(new Point(getWidth()/2, getHeight()/2))
				.addVertex(new Point(PADDING, getHeight()))
				.addVertex(new Point(0, getHeight()))
				.build();
		polygonBackward = new Polygon.Builder()
				.addVertex(new Point(getWidth()-PADDING, getHeight()))
				.addVertex(new Point(PADDING, getHeight()))
				.addVertex(new Point(getWidth()/2, getHeight()/2))
				.build();
		polygonBackwardRight = new Polygon.Builder()
				.addVertex(new Point(getWidth()/2, getHeight()/2))
				.addVertex(new Point(getWidth(), getHeight()/2))
				.addVertex(new Point(getWidth(), getHeight()))
				.addVertex(new Point(getWidth()-PADDING, getHeight()))
				.build();
		polygonStop = new Polygon.Builder()
				.addVertex(new Point(getWidth()/2-PADDING, getHeight()/2-PADDING))
				.addVertex(new Point(getWidth()/2+PADDING, getHeight()/2-PADDING))
				.addVertex(new Point(getWidth()/2+PADDING, getHeight()/2+PADDING))
				.addVertex(new Point(getWidth()/2-PADDING, getHeight()/2+PADDING))
				.build();
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(calculateMeasure(widthMeasureSpec), calculateMeasure(heightMeasureSpec));
		initVert();
	}

	private int calculateMeasure(int measureSpec) {
		int result = (int) (DEFAULT_SIZE * getResources().getDisplayMetrics().density);
		
		int specMode = MeasureSpec.getMode(measureSpec);
		int specSize = MeasureSpec.getSize(measureSpec);
		
		if (specMode == MeasureSpec.EXACTLY) {
			result = specSize;
		} else if (specMode == MeasureSpec.AT_MOST) {
			result = Math.min(result, specSize);
		}
		
		return result;
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		canvas.save();
		canvas.drawRect(getWidth()/2-PADDING, getHeight()/2-PADDING, getWidth()/2+PADDING, getHeight()/2+PADDING, mPaint);
		canvas.drawCircle(getWidth()/2, getHeight()/2, 80, mPaint);
		canvas.drawLine(0+PADDING, 0, getWidth()-PADDING, getHeight(), mPaint);
		canvas.drawLine(getWidth()-PADDING, 0, 0+PADDING, getHeight(), mPaint);
		canvas.drawLine(0, getHeight()/2, getWidth(), getHeight()/2, mPaint);
		
		if (drawTouchPoint) {
			canvas.drawCircle(touchPoint.x, touchPoint.y, 20, mTouchPaint);
			
			if (isInside(polygonStop, touchPoint)) {
				if (!where.equals("STOP")) {
					if (directionListener != null) {
						directionListener.goStop();
					}
					where = "STOP";
				}
			} else {
				if (isInside(polygonForwardLeft, touchPoint)) {
					if (!where.equals("FORWARD_LEFT")) {
						if (directionListener != null) {
							directionListener.goForwardLeft();
						}
						where = "FORWARD_LEFT";
					}
				} else if (isInside(polygonForward, touchPoint)) {
					if (!where.equals("FORWARD")) {
						if (directionListener != null) {
							directionListener.goForward();
						}
						where = "FORWARD";
					}
				} else if (isInside(polygonForwardRight, touchPoint)) {
					if (!where.equals("FORWARD_RIGHT")) {
						if (directionListener != null) {
							directionListener.goForwardRight();
						}
						where = "FORWARD_RIGHT";
					}
				} else if (isInside(polygonBackwardLeft, touchPoint)) {
					if (!where.equals("BACKWARD_LEFT")) {
						if (directionListener != null) {
							directionListener.goBackwardLeft();
						}
						where = "BACKWARD_LEFT";
					}
				} else if (isInside(polygonBackward, touchPoint)) {
					if (!where.equals("BACKWARD")) {
						if (directionListener != null) {
							directionListener.goBackward();
						}
						where = "BACKWARD";
					}
				} else if (isInside(polygonBackwardRight, touchPoint)) {
					if (!where.equals("BACKWARD_RIGHT")) {
						if (directionListener != null) {
							directionListener.goBackwardRight();
						}
						where = "BACKWARD_RIGHT";
					}
				}
			}
			canvas.drawText(where + " x: " + touchPoint.x + ", y: " + touchPoint.y, touchPoint.x-PADDING, touchPoint.y-PADDING, mPaint);
		}
		canvas.restore();
	}
	
	/**
	 * Check if point inside the polygon
	 * 
	 * @param polygon
	 * @param point
	 */
	private static boolean isInside(Polygon polygon, Point point)
	{
		boolean contains = polygon.contains(point);
		
		return contains;
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		float eventX = event.getX();
		float eventY = event.getY();
		
		touchPoint.x = (int) eventX;
		touchPoint.y = (int) eventY;
		
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN :
			drawTouchPoint = true;
			break;
		case MotionEvent.ACTION_MOVE :
			break;
		case MotionEvent.ACTION_UP :
			drawTouchPoint = false;
			break;
		default :
			return false;
		}
		
		invalidate();
		return true;
	}
	
//	boolean pnpoly(float vertx[], float verty[], float testx, float testy) {
//		int xNLength = vertx.length;
//		int yNLength = verty.length;
//		boolean returnVal = false;
//		
//		if (xNLength != yNLength) {
//			return returnVal;
//		}
//		
//		for (int i = 0, j= xNLength - 1; i < xNLength; j = i++) {
//			if (((verty[i] > testy) != (verty[j] > testy)) && (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i])) {
//				returnVal = !returnVal;
//			}
//		}
//		
//		return returnVal;
//	}
}
